﻿using LitJson;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GersonFrame.Tool;
using GersonFrame.ABFrame;

namespace GersonFrame
{

    public enum AudioType
    {
        BackMusic,
        NormalMusic,//同时存在一个音效源
        MutipleMusic,//同时存在多个音效源
    }

    [System.Serializable]
    public class AudioInfo
    {
        public string AudioName;
        public float Volume;
        public int Loop;
        public AudioClip Clip;
        public string AudioType;
        public string Desc;//描述
        public float Delay =0;//延时播放
    }

    /// <summary>
    /// 音效播放信息
    /// </summary>
    [System.Serializable]
    public class AudioPlayerInfo
    {
        public string AudioName;
        private int MaxCount;
        private float MinPlayInternal = 0.1f;
        private int CurrentCount=0;
        private float lastPlayTime=-1;

        public AudioPlayerInfo(string audioName,int maxcount,float minPlayInternal)
        {
            this.AudioName = audioName;
            this.MaxCount = maxcount;
            this.MinPlayInternal = minPlayInternal;
            lastPlayTime = -1;
        }

        public void ResetCount()
        {
            this.CurrentCount = 0;
            lastPlayTime = Time.realtimeSinceStartup;
        }


        /// <summary>
        /// 是否可以播放
        /// </summary>
        /// <returns></returns>
        public bool CanPlay()
        {
            if (lastPlayTime==-1)
            {
                lastPlayTime = Time.realtimeSinceStartup;
                this.CurrentCount++;
                return true;
            }
            else
            {
                float timedis = Time.realtimeSinceStartup -lastPlayTime;
                if (timedis<=this.MinPlayInternal || this.CurrentCount>=MaxCount)
                {
                    return false;
                }
                else if (timedis > this.MinPlayInternal)
                {
                    this.ResetCount();
                    this.CurrentCount++;
                    return true;
                }
                else
                {
                    this.CurrentCount++;
                    return true;
                }
            }
        }

    }

    /// <summary>
    /// 游戏音效设置信息
    /// </summary>
    public class AudioSettingInfo
    {
        public bool BackMusicIsMute = false;
        public bool AudioMuscIsMute = false;
    }

    public class AudioManger : MonoSingleton<AudioManger>
    {

        GameObject m_audioParent;

        [Tooltip("编辑器音量大小 对移动端无效")]
        [Range(0,1)]
        public float m_Valume = 1;
        [Tooltip("最短时间内的最大播放次数")]
        [Range(1, 50)]
        public int MaxPlayCount = 5;
        [Tooltip("最短播放间隔")]
        [Range(0.01f, 10)]
        public float MinPlayInternal = 0.1f;

        private const string m_audioclipPath = "Assets/AudioClips/";


        private SimpleObjectPool<AudioSource> m_mutipleAudioSourcePool = new SimpleObjectPool<AudioSource>(GetMutipleAudioSources);

        private Dictionary<string, AudioInfo> m_audioDic = new Dictionary<string, AudioInfo>();
        private Dictionary<string, AudioPlayerInfo> m_audioPlayeInfoDic = new Dictionary<string, AudioPlayerInfo>();
        private  AudioSource m_backAudioSource;         
        private  AudioSource m_normalAudioSource;         

        /// <summary>
        /// 背景音乐
        /// </summary>
        public AudioSource BackAudioSource
        {
            get
            {
                if (m_backAudioSource == null)
                    this.m_backAudioSource = this.gameObject.AddComponent<AudioSource>();
                return this.m_backAudioSource;
            }
        }
        /// <summary>
        ///  普通音效源
        /// </summary>
        public AudioSource NormalAudioSource
        {
            get
            {
                if (m_normalAudioSource == null)
                    this.m_normalAudioSource = this.gameObject.AddComponent<AudioSource>();
                return this.m_normalAudioSource;
            }
        }

        //==============================游戏音效设置数据=============================
        /// <summary>
        /// 获取音效设置
        /// </summary>
        /// <returns></returns>
        public  AudioSettingInfo GetMusicSettingData()
        {
            AudioSettingInfo settinginfo = PlayerPrefsTool.GetData<AudioSettingInfo>("AudioSetting", new AudioSettingInfo());
            return settinginfo;
        }

        /// <summary>
        /// 保存音效设置
        /// </summary>
        /// <param name="backmusicIsmute">背景音效</param>
        /// <param name="audioMuscIsMute">普通音效</param>
        public  void SetMusicSettingData(bool backmusicIsmute,bool audioMuscIsMute)
        {
            AudioSettingInfo settinginfo= PlayerPrefsTool.GetData<AudioSettingInfo>("AudioSetting", new AudioSettingInfo());
            settinginfo.AudioMuscIsMute = audioMuscIsMute;
            settinginfo.BackMusicIsMute = backmusicIsmute;
            PlayerPrefsTool.SetData<AudioSettingInfo>("AudioSetting", settinginfo);
            if (settinginfo.BackMusicIsMute) BackAudioSource.mute = true;
            else BackAudioSource.mute = false;
            if (settinginfo.AudioMuscIsMute) NormalAudioSource.mute = true;
            else NormalAudioSource.mute = false;
        }


        /// <summary>
        /// 加载音效文件
        /// </summary>
        public void LoadAudioClips()
        {

#if !UNITY_EDITOR
              m_Valume = 1;
#endif
            m_audioParent = new GameObject("AudioRoot");
            TextAsset audiotext=ResourceManager.Instance.LoadResource<TextAsset>("Assets/Configs/AudioConfig/AudioConfig.json");
            if (audiotext==null)
            {
                MyDebuger.LogError("not found AudioInfo in Resource Configs/AudioConfig");
                return;
            }
            List<AudioInfo> audioList= JsonMapper.ToObject <List<AudioInfo>>(audiotext.text);
            if (audioList.Count<1) MyDebuger.LogWarning("音乐配置文件中没有找到可用信息");
            for (int i = 0; i < audioList.Count; i++)
            {
                AudioInfo audiInfo = audioList[i];
                AudioClip clip=ResourceManager.Instance.LoadResource<AudioClip>(m_audioclipPath+audiInfo.AudioName);
                if (clip==null)
                {
                    MyDebuger.LogError("not found "+ m_audioclipPath + audiInfo.AudioName);
                    continue;
                }
                audiInfo.Clip = clip;
                string[] audioName = audiInfo.AudioName.Split('.');
                m_audioDic[audioName[0]] = audiInfo;
                AudioPlayerInfo audioPlayerInfo = new AudioPlayerInfo(audioName[0],this.MaxPlayCount,this.MinPlayInternal);
                m_audioPlayeInfoDic[audioName[0]] = audioPlayerInfo;
            }
            MyDebuger.Log("音效信息加载完毕");
        }


        /// <summary>
        /// 播放音乐
        /// </summary>
        public void PlayeAudio(string audioName)
        {
            if (this.m_audioDic.ContainsKey(audioName)&& m_audioPlayeInfoDic.ContainsKey(audioName))
            {
                if (m_audioPlayeInfoDic[audioName].CanPlay())
                {
                    AudioInfo audioInfo = this.m_audioDic[audioName];
                    this.AudioSourcePlay(audioInfo);
                }
            }
            else MyDebuger.LogError("play audio fail  not found audio " + audioName);
        }

        private AudioSource GetPlayAudioSource(string audioType)
        {
            AudioType  tempaudioType = (AudioType)System.Enum.Parse(typeof(AudioType), audioType);
            switch (tempaudioType)
            {
                case AudioType.BackMusic:
                    if (this.GetMusicSettingData().BackMusicIsMute) BackAudioSource.mute = true;
                    BackAudioSource.playOnAwake = false;
                    return BackAudioSource;
                case AudioType.NormalMusic:
                    if (this.GetMusicSettingData().AudioMuscIsMute) NormalAudioSource.mute = true;
                    NormalAudioSource.playOnAwake = false;
                    return NormalAudioSource;
                case AudioType.MutipleMusic:
                    if (this.GetMusicSettingData().AudioMuscIsMute) return null;
                    AudioSource audiosource=  this.m_mutipleAudioSourcePool.Allocate();
                    audiosource.transform.SetParent(m_audioParent.transform);
                    audiosource.playOnAwake = false;
                    audiosource.gameObject.Show();
                    return audiosource;
                default:
                    MyDebuger.LogError("can not found audio type " + audioType);
                    return null;
            }
    }

        /// <summary>
        /// 获得重叠播放音效播放
        /// </summary>
        /// <returns></returns>
        private static AudioSource GetMutipleAudioSources()
        {
            GameObject go = new GameObject("mutipleAudio");
            return go.AddComponent<AudioSource>();
        }
        private AudioSource AudioSourcePlay(AudioInfo audoinfo)
        {
            AudioSource audiosource = this.GetPlayAudioSource(audoinfo.AudioType);
            if (audiosource == null) return audiosource;
            audiosource.clip = audoinfo.Clip;
            audiosource.volume = audoinfo.Volume* m_Valume;
            audiosource.loop = audoinfo.Loop == 1;
            audiosource.PlayDelayed(audoinfo.Delay);
            return audiosource;
        }

        /// <summary>
        /// 暂停音效
        /// </summary>
        /// <param name="audioName"></param>
        public void PauseAudio(string audioName)
        {
            if (this.m_audioDic.ContainsKey(audioName))
            {
                if (this.m_audioDic[audioName].AudioType!=AudioType.MutipleMusic.ToString())
                {
                    this.GetPlayAudioSource(audioName).Pause();
                }
            }
        }

        /// <summary>
        /// 恢复音效播放
        /// </summary>
        /// <param name="audioName"></param>
        public void ResumeAudio(string audioName)
        {
            if (this.m_audioDic.ContainsKey(audioName))
            {
                if (this.m_audioDic[audioName].AudioType != AudioType.MutipleMusic.ToString())
                {
                    this.GetPlayAudioSource(audioName).UnPause();
                }
            }
        }

        /// <summary>
        ///停止音效播放
        /// </summary>
        /// <param name="audioName"></param>
        public void StopAudio(string audioName)
        {
            if (this.m_audioDic.ContainsKey(audioName))
            {
                if (this.m_audioDic[audioName].AudioType != AudioType.MutipleMusic.ToString())
                {
                    this.GetPlayAudioSource(audioName).Stop();
                }
            }
        }

        /// <summary>
        /// 播放重叠音效
        /// </summary>
        public void PlayMutipleAudio(string audioName)
        {
            if (this.m_audioDic.ContainsKey(audioName) && m_audioPlayeInfoDic.ContainsKey(audioName))
            {
                if (!m_audioPlayeInfoDic[audioName].CanPlay()) return;
                AudioInfo info= this.m_audioDic[audioName];
                string audiotype = info.AudioType;
                if (audiotype != AudioType.MutipleMusic.ToString())
                    MyDebuger.LogWarning("audio type is wrong " + audiotype+" name="+audioName);
                else this.AudioSourcePlay(info);
            }
            else
            {
                MyDebuger.LogError("PlayMutipleAudio play audio fail  not found audio " + audioName);
            }
        }

        private void Update()
        {
            for (int i = 0; i < m_mutipleAudioSourcePool.UsingCount; i++)
            {
                AudioSource source = m_mutipleAudioSourcePool.mUsingStack[i];
                if (!source.isPlaying)
                {
                    source.gameObject.Hide();
                    this.m_mutipleAudioSourcePool.Recycle(source);
                }
            }
        }



   

    }
}
